/*
 * File:   Lab7Main.cpp
 * Author: jorgeorm
 *
 * Created on 13 de enero de 2012, 04:20 PM
 */

#include <QtGui/QApplication>
#include <cstdlib>
#include <cstdio>
using namespace std;

#include "ProblemaPoblacionL.h"
#include "Derivada_DifDivididas.h"
#include "IntegralTrapesioExtendido.h"

int main(int argc, char *argv[]) {
    long double xs[]={
        0,
        10,
        20,
        30,
        40,
        50,
        60,
        70,
        80,
        90,
        100
    };
    long double hs[]={
        0.1,
        0.001,
        0.000000000001
    };
    int anios[]={
        1800,
        1810,
        1820,
        1830,
        1840,
        1850,
        1860,
        1870,
        1880,
        1890,
        1900
    };
    
    int anios_2[]={
        1800,
        1850,
        1890
    };
    
    int tamDats=10;
    int punto;
    int anho; //Para primer punto
    int h;//Para primer punto
    long double t;//Para primer punto
    long double t2; //para primer punto
    long double t3; //para primer punto
    int metodo; // Para primer punto
    int dif_div; // Para primer punto
    long double derivada;//Para primer punto
    long double derivadaReal;
    long double errorAprox;
    ProblemaPoblacionL * objProblem;

    
    Derivada_DifDivididas * obj_DifDiv;
    
    while(punto>2 || punto<1)
    {
    cout<<"Laboratorio 7: Derivacion e Integracion: "<<endl;
    cout<<"¿Qué punto desea probar?: "<<endl;
    cout<<"[1] - Crecimiento poblacion Ciudad Gotica - Derivadas"<<endl;
    cout<<"[2] - Numeros primos entre a y b - Integrales"<<endl;
    cin>>punto;
    if(punto>2 || punto<1) cout<<"##########VALOR NO VALIDO##########"<<endl;
    }
    
    switch (punto)
    {
        case 1:
            cout<<"¿En qué año desea calcular la razón de cambio?"<<endl;
            anho=0;
            metodo=0;
            while(anho>3 || anho<1)
            {
                cout<<"[1] - 1800"<<endl;
                cout<<"[2] - 1850"<<endl;
                cout<<"[3] - 1890"<<endl;
                cin>>anho;
                if(anho>3 || anho<1) cout<<"##########VALOR NO VALIDO##########"<<endl;
            }
            
            for(int i=0; i<tamDats; i++)
            {
                if(anios[i]==anios_2[anho-1])t=xs[i];
            }

            cout<<"¿Qué método desea usar?"<<endl;
            while(metodo>2 || metodo<1)
            {
                cout<<"[1] - Interpolacion polinomial (Lagrange)"<<endl;
                cout<<"[2] - Diferencias divididas"<<endl;
                cin>>metodo;
                if(metodo>2 || metodo<1) cout<<"##########VALOR NO VALIDO##########"<<endl;
            }

            switch(metodo)
            {
                case 1:
                    objProblem= new ProblemaPoblacionL(xs, tamDats, anios);
                     objProblem->pedirAnhio();
                     objProblem->~ProblemaPoblacionL();
                     objProblem=NULL;
                     
                    break;

                case 2:
                    h=0;
                    dif_div=0;
                    cout<<"Escoja la distancia h:"<<endl;
                    while(h>3 || h<1)
                    {
                        cout<<"[1] - 0.1"<<endl;
                        cout<<"[2] - 0.001"<<endl;
                        cout<<"[3] - 1x10^-12"<<endl;
                        cin>>h;
                        if(h>3 || h<1) cout<<"##########VALOR NO VALIDO##########"<<endl;
                    }

                    while(dif_div>3 || dif_div<1)
                    {
                        cout<<"Y el tipo de diferencia dividida a usar: "<<endl;
                        cout<<"[1] - Hacia adelante"<<endl;
                        cout<<"[2] - Hacia atras"<<endl;
                        cout<<"[3] - Centradas"<<endl;
                        cin>>dif_div;
                            if(dif_div>3 || dif_div<1) cout<<"##########VALOR NO VALIDO##########"<<endl;
                    }
                    
                    obj_DifDiv = new Derivada_DifDivididas(xs, tamDats);
                    switch(dif_div)
                    {
                        case 1:
                            
                            t2=t+hs[h-1];
                            derivada=obj_DifDiv->CalcularAdelante(t, t2, hs[h-1]);
                            derivadaReal=obj_DifDiv->derivadaTeorica(t);
                            errorAprox=obj_DifDiv->ErrorAproxAdelAtras(t, t2, hs[h-1]);
                            
                            printf("El valor de la derivada para t= %#8.1Le por diferencias divididas hacia "
                                    "adelante es f'(t)= %#8.10Le\n", t, derivada);
                            printf("El valor de la derivada real para t= %#8.10Le es de "
                                    "F'(x)= %#8.10Le\n", t, derivadaReal);
                            printf("El error aproximado para la derivada aproximada por diferencias divididas"
                                    " hacia adelante es de e = %#8.10Le\n", errorAprox);
                            break;
                            
                        case 2:
                            
                            t2=t-hs[h-1];
                           
                            derivada = obj_DifDiv->CalcularAtras(t2, t, hs[h-1]);
                            derivadaReal = obj_DifDiv->derivadaTeorica(t);
                            errorAprox = obj_DifDiv->ErrorAproxAdelAtras(t, t2, hs[h-1]);
                            printf("El valor de la derivada para t= %#8.10Le por diferencias divididas hacia "
                                    "atras es f'(t)= %#8.10Le\n", t, derivada);
                            printf("El valor de la derivada real para t= %#8.10Le es de "
                                    "F'(x)= %#8.10Le\n", t, derivadaReal);
                            printf("El error aproximado para la derivada aproximada por diferencias divididas"
                                    " hacia atras es de e = %#8.10Le\n", errorAprox);
                            break;
                            
                        case 3:
                            
                            t2=t-hs[h-1];
                            t3=t+hs[h-1];
                            derivada = obj_DifDiv->CalcularCentradas(t2, t3, hs[h-1]);
                            derivadaReal = obj_DifDiv->derivadaTeorica(t);
                            errorAprox = obj_DifDiv->ErrorAproxCentradas(t2, t, t3, hs[h-1]);
                            printf("El valor de la derivada para t= %#8.10Le por diferencias divididas "
                                    "centradas es f'(t)= %#8.10Le\n", t, derivada);
                            printf("El valor de la derivada real para t= %#8.10Le es de "
                                    "F'(x)= %#8.10Le\n", t, derivadaReal);
                            printf("El error aproximado para la derivada aproximada por diferencias divididas"
                                    " centradas es de e = %#8.10Le\n", errorAprox);
                            break;
                    }

                    break;
            }
            break;
            
        case 2: 
            long double valsN[]={
                1.0,
                2.0, 
                5.0,
                30
            };
            long double limInf=2;
            long double limSup=32;
            long double valReal=12.559928397;
            cout<<"Intervalos a= 2 y b = 32"<<endl;
            IntegralTrapesioExtendido * objInt= new IntegralTrapesioExtendido(valReal);
            long double resultInt=0;
            long double error=0;
            for(int i=0;i<4;i++)
            {
                resultInt=objInt->reglaTrapesoide(valsN[i],limInf,limSup);
                error=objInt->getErrorReal();
                printf("El valor de la integral aproximada para N= %#8.1Le, Fue: %#8.10Le Et: %#8.10Le\n", valsN[i], resultInt, error);
            }
            objInt->~IntegralTrapesioExtendido();
            objInt=NULL;
            
            break;
    }
    
        
    return 0;
//    return app.exec();
}


